package com.tang.framework.delay.support;

import com.tang.common.constant.delay.DelayConstant;
import com.tang.framework.config.SpringApplication;
import com.tang.framework.delay.support.domain.Message;
import jodd.util.ThreadFactoryBuilder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;

import java.lang.reflect.Method;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author tang jun liang
 * @Date 2023/4/20 16:39
 */

@Slf4j
public class DelayFinalExecute {

    private final RedissonClient redissonClient;

    private final RBlockingQueue<Message<?>> blockingQueue;





    public DelayFinalExecute(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
        blockingQueue = redissonClient.getBlockingQueue(DelayConstant.FINAL_QUEUE_KEY);
//        run();
    }

    private final ThreadPoolExecutor executor = new ThreadPoolExecutor(
            1, 1, 1L,
            TimeUnit.HOURS, new LinkedBlockingQueue<>(), ThreadFactoryBuilder.create()
            .withDaemon(true)
            .withNameFormat("delayFinal:%s")
            .get());


    private void run() {
        new Thread(this::loopUp).start();
    }

    @SneakyThrows
    private void loopUp() {
        for (; ; ) {
            Message<?> message = blockingQueue.take();
            Message.MethodInfo methodInfo = message.getMethodInfo();
            Class<?> clazz = methodInfo.getClazz();
            Object object = SpringApplication.getBean(clazz);
            Method invokeMethod = clazz.getDeclaredMethod(methodInfo.getMethodName(), Message.class);
            try{
                invokeMethod.invoke(object, message);
            }catch (Exception e){
                message.increment();
                blockingQueue.offer(message);
            }

        }
    }

}
